import axios from 'axios'
import {
  tokenName,
  publicPath,
  mock
} from '@/configs'
import store from '@/store'
import Vue from 'vue'
import mockServer from '@/mock'

const handleData = ({ request, data, headers }) => {
  const responseType = request.responseType
  // 如果请求响应类型为blob
  if (responseType === 'blob') {
    const contentType = headers['content-type']
    // 返回图片
    if (contentType && contentType.startsWith('image')) {
      return {
        data,
        fileName: decodeURIComponent(request.responseURL.split('/').pop())
      }
    }
    const contentDisposition = headers['content-disposition']
    // 同时确实有返回文件流
    if (contentDisposition) {
      const fileName = contentDisposition.split(';')[1].split('=')[1]
      return {
        data,
        fileName: decodeURI(escape(fileName))
      }
    } else {
      // 如果不是文件流,将文件流=>json
      const contentType = headers['content-type'].split(';')[0]
      if (contentType === 'application/json') {
        const fileReader = new FileReader()
        fileReader.readAsText(data, 'utf-8')
        fileReader.onload = function () {
          return handleNormalData({ data: JSON.parse(fileReader.result) })
        }
      }
    }
  } else {
    return handleNormalData({ data })
  }
}

function handleNormalData ({ data }) {
  // 滑块验证码的请求，直接返回
  if (data.repCode) {
    return data
  }
  if (Array.isArray(data)) return data
  // 登录过期了
  if (data.code === 401) {
    store.dispatch('user/resetAll')
    const url = localStorage.getItem('casLogoutUrl')
    if (url) {
      window.location.href = url
      localStorage.removeItem('casLogoutUrl')
    }
    return
  }
  if ((parseInt(data.code) === 200) && (data.status || data.success)) {
    return data.data ?? data
  }
  Vue.prototype.$message.error(data.message || data.msg)
  return Promise.reject(data.message || data.msg)
}
const baseURL = (process.env.NODE_ENV === 'production' && IS_NGINX === 'false') ? '/' : '/api'

const instance = axios.create({
  timeout: 100000,
  baseURL,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

export const external = axios.create({
  timeout: 100000,
  baseURL,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

instance.interceptors.request.use(
  (config) => {
    const token = store.state.user.token
    if (token) {
      config.headers[tokenName] = token
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

instance.interceptors.response.use(
  (response) => handleData(response),
  (error) => {
    const { response } = error
    Vue.prototype.$message.error('操作失败！')
    return Promise.reject(response || error)
  }
)

export default {
  baseURL,
  upload (url, params = {}, configs) {
    const fd = new FormData()
    for (const i in params) {
      fd.append(i, params[i])
    }
    const axiosConfigs = {
      url,
      method: 'POST',
      data: fd
    }
    if (configs === true) {
      // 开启上传进度显示
      axiosConfigs.onUploadProgress = onUploadProgress
      return instance(axiosConfigs).then(r => {
        store.commit('utils/setFileStateInfo', {
          visible: false
        })
        return r
      })
    } else if (typeof configs === 'object') {
      Object.assign(axiosConfigs, configs)
    }
    return instance(axiosConfigs)
  },
  singleTableOperation (configs) {
    return this.post(configs.url || '/SingleTable/curd', {
      appId: configs.appId || 'YSJC',
      bzCode: configs.bzCode || 'YSJC',
      metaSet: configs.metaSet,
      viewCode: configs.viewCode,
      methodCode: configs.methodCode || 'select',
      methodParams: JSON.stringify(configs.methodParams),
      pageNum: configs.pageNum,
      pageSize: configs.pageSize
    })
  },
  curdCreate (configs) {
    return this.post('/curd/curdCreate', {
      appId: configs.appId || 'MAN_HOUR',
      bzCode: configs.bzCode || 'MAN_HOUR',
      curdId: configs.curdId,
      methodCode: configs.methodCode,
      methodParams: configs.methodParams
    })
  },
  post (url, data, useJson = true) {
    if (mock) {
      return mockServer.query(url, data)
    }
    // 方便调试
    if (url === '/grid/getTableData') {
      url = `/grid/v2/getTableData/${data.appId}/${data.bzCode}/${data.metaSet}-${data.methodCode || 'select'}`
    } else if (url === '/grid/getColumnsData') {
      url = `/grid/v2/getColumnsData/${data.appId}/${data.bzCode}/${data.metaSet}`
    } else if (url === '/SingleTable/curd') {
      url = `/SingleTable/v2/curd/${data.appId}/${data.bzCode}/${data.metaSet}-${data.methodCode || 'select'}`
    } else if (url === '/view/getTableData') {
      url = `/view/v2/getTableData/${data.appId}/${data.bzCode}/${data.viewCode || data.metaSet}-${data.methodCode || 'select'}`
    } else if (url === '/view/getColumnsData') {
      url = `/view/v2/getColumnsData/${data.appId}/${data.bzCode}/${data.viewCode || data.metaSet}`
    } else if (url === '/tree/data') {
      url = `/tree/v2/data/${data.treeConfigId}-tree`
    } else if (url === '/dic/getDicData') {
      url = `/dic/v2/getDicData/${data.dicKey}-dic`
    } else if (url === '/dic/getDicTreeData') {
      url = `/dic/v2/getDicTreeData/${data.dicKey}-dic`
    }
    const fd = new FormData()
    if (data && !useJson) {
      for (const key in data) {
        if (Object.hasOwnProperty.call(data, key)) {
          const value = data[key]
          if (typeof value === 'object') {
            fd.append(key, JSON.stringify(value))
          } else {
            fd.append(key, value)
          }
        }
      }
    }
    return instance({
      url,
      method: 'POST',
      data: useJson ? data : fd
    })
  },
  get (url, params) {
    return instance({
      url,
      method: 'GET',
      params
    })
  },
  getFileStream (url, params, configs) {
    const axiosConfigs = {
      url,
      method: 'get',
      params,
      responseType: 'blob'
    }
    if (configs === true) {
      // 开启下载进度显示
      axiosConfigs.onDownloadProgress = onDownloadProgress
      return instance(axiosConfigs).then(r => {
        store.commit('utils/setFileStateInfo', {
          visible: false
        })
        return r
      })
    } else if (typeof configs === 'object') {
      Object.assign(axiosConfigs, configs)
    }
    return instance(axiosConfigs)
  },
  getFileStreamByPost (url, data, configs = true) {
    const axiosConfigs = {
      url,
      method: 'post',
      data,
      responseType: 'blob'
    }
    if (configs === true) {
      // 开启下载进度显示
      axiosConfigs.onDownloadProgress = onDownloadProgress
      return instance(axiosConfigs).then(r => {
        store.commit('utils/setFileStateInfo', {
          visible: false
        })
        return r
      })
    } else if (typeof configs === 'object') {
      Object.assign(axiosConfigs, configs)
    }
    return instance(axiosConfigs)
  },
  downloadBlobFile (blob, fileName) {
    const link = document.createElement('a')
    link.style.display = 'none'
    link.href = URL.createObjectURL(blob)
    link.setAttribute('target', '_blank')
    link.setAttribute('download', fileName)
    document.body.appendChild(link)
    link.click()
    URL.revokeObjectURL(link.href)
    document.body.removeChild(link)
  },
  previewPdf (pathStr, nameStr) {
    // pathStr 和 nameStr 如果是多个文件则以 `,` 分隔
    window.open('/pdf-viewer/pdf/web/viewerIframe.html?pdfs=' + pathStr + '&names=' + nameStr + '&baseurl=' + publicPath)
  },
  downloadFileByUrl (url, configs) {
    return this.getFileStream('/file/download/resource', {
      resource: url
    }, configs)
  },
  copyTextToClipboard (text) {
    const textArea = document.createElement('textarea')
    textArea.style.position = 'fixed'
    textArea.style.visibility = '-10000px'
    textArea.value = text
    document.body.appendChild(textArea)
    textArea.focus()
    textArea.select()

    if (!document.execCommand('copy')) {
      Vue.prototype.warning('浏览器暂不支持此操作！')
    } else {
      Vue.prototype.$message.success('复制成功！')
    }
    document.body.removeChild(textArea)
  },
  async formDataPost (url, params = {}, needAreaCode = true, requestType = 'POST', isJson = false, externalHeaders = {}) {
    if (needAreaCode) {
      Object.assign(params, { areaCode: store.state.user.userInfo.dept.LEADER })
    }
    let query = new URLSearchParams(params).toString()
    if (isJson) {
      query = JSON.stringify(params)
    }
    const res = await fetch(url, {
      method: requestType,
      headers: {
        'Content-Type': isJson ? 'application/json' : 'application/x-www-form-urlencoded',
        ...externalHeaders
      },
      body: query
    })
    const response = await res.json()
    if (response.data && response.code === 200) {
      if (response.data?.data) {
        return response.data.data
      } else {
        return response.data
      }
    } else {
      return Promise.reject(response)
    }
  },
  async formDataGet (url, params = {}, isJson = false) {
    const query = new URLSearchParams(params).toString()
    const queryUrl = url + '?' + query
    const res = await fetch(queryUrl, {
      method: 'GET',
      headers: {
        'Content-Type': isJson ? 'application/json' : 'application/x-www-form-urlencoded'
      }
    })
    const response = await res.json()
    if (response.data && response.code === 200) {
      if (response.data?.data) {
        return response.data.data
      } else {
        return response.data
      }
    } else {
      return Promise.reject(response)
    }
  }
}

function onUploadProgress (e) {
  const percentage = parseInt(e.loaded / e.total * 100)
  store.commit('utils/setFileStateInfo', {
    visible: true,
    text: '正在上传文件，请耐心等待',
    percentage
  })
}

function onDownloadProgress (e) {
  if (!e.total) return
  const percentage = parseInt(e.loaded / e.total * 100)
  store.commit('utils/setFileStateInfo', {
    visible: true,
    text: '正在下载文件，请耐心等待',
    percentage
  })
}
